sync to home
authorJonathan Blandford <jrb@src.gnome.org>
Wed, 22 Nov 2000 05:16:37 +0000 (05:16 +0000)
committerJonathan Blandford <jrb@src.gnome.org>
Wed, 22 Nov 2000 05:16:37 +0000 (05:16 +0000)
gtk/gtktreemodelsort.c
gtk/treestoretest.c
tests/treestoretest.c

index 06bcc2f5e9033413623f71f4a2f52363c29fe553..ca7c3052685d2554eae46f6b96e09703f675990d 100644 (file)
@@ -46,11 +46,20 @@ struct _SortElt
   gint offset;
 };
 
+typedef struct _SortData SortData;
+struct _SortData
+{
+  GtkTreeModel *model;
+  gint sort_col;
+  GValueCompareFunc func;
+};
+
 static guint tree_model_sort_signals[LAST_SIGNAL] = { 0 };
 
 
 #define get_array(e,t) ((GArray *)((e)->parent?(e)->parent->children:GTK_TREE_MODEL_SORT(t)->root))
 
+
 static void         gtk_tree_model_sort_init            (GtkTreeModelSort      *tree_model_sort);
 static void         gtk_tree_model_sort_class_init      (GtkTreeModelSortClass *tree_model_sort_class);
 static void         gtk_tree_model_sort_tree_model_init (GtkTreeModelIface     *iface);
@@ -104,13 +113,21 @@ static void         gtk_tree_model_sort_unref_iter      (GtkTreeModel          *
                                                         GtkTreeIter           *iter);
 
 /* Internal functions */
-static void         gtk_tree_model_sort_build_level     (GtkTreeModelSort      *tree_model_sort,
-                                                        SortElt               *place);
-static void         gtk_tree_model_sort_free_level      (GArray                *array);
-gint                g_value_string_compare_func         (const GValue          *a,
-                                                        const GValue          *b);
-gint                g_value_int_compare_func            (const GValue          *a,
-                                                        const GValue          *b);
+static GtkTreePath *gtk_tree_model_sort_convert_path_real (GtkTreeModelSort *tree_model_sort,
+                                                          GtkTreePath      *child_path,
+                                                          gboolean          build_children);
+static void         gtk_tree_model_sort_build_level       (GtkTreeModelSort *tree_model_sort,
+                                                          SortElt          *place);
+static void         gtk_tree_model_sort_free_level        (GArray           *array);
+static GFunc        gtk_tree_model_sort_get_func          (GtkTreeModelSort *tree_model_sort);
+static gint         gtk_tree_model_sort_func              (gconstpointer     a,
+                                                          gconstpointer     b,
+                                                          gpointer          user_data);
+static gint         g_value_string_compare_func           (const GValue     *a,
+                                                          const GValue     *b);
+static gint         g_value_int_compare_func              (const GValue     *a,
+                                                          const GValue     *b);
+
 
 
 GtkType
@@ -318,53 +335,11 @@ GtkTreePath *
 gtk_tree_model_sort_convert_path (GtkTreeModelSort *tree_model_sort,
                                  GtkTreePath      *child_path)
 {
-  GtkTreePath *retval;
-  GArray *array;
-  gint *indices;
-  gint i = 0;
-
-  if (tree_model_sort->root == NULL)
-    gtk_tree_model_sort_build_level (tree_model_sort, NULL);
-
-  retval = gtk_tree_path_new ();
-  array = (GArray *) tree_model_sort->root;
-  indices = gtk_tree_path_get_indices (child_path);
-
-  do
-    {
-      SortElt *elt;
-      gboolean found = FALSE;
-      gint j;
-
-      if ((array->len < indices[i]) || (array == NULL))
-       {
-         gtk_tree_path_free (retval);
-         return NULL;
-       }
-
-      elt = (SortElt *) array->data;
-      for (j = 0; j < array->len; j++, elt++)
-       {
-         if (elt->offset == indices[i])
-           {
-             found = TRUE;
-             break;
-           }
-       }
-      if (! found)
-       {
-         gtk_tree_path_free (retval);
-         return NULL;
-       }
-
-      gtk_tree_path_prepend_index (retval, j);
-      if (elt->children == NULL)
-       gtk_tree_model_sort_build_level (tree_model_sort, elt);
-      i++;
-    }
-  while (i < gtk_tree_path_get_depth (child_path));
+  g_return_val_if_fail (tree_model_sort != NULL, NULL);
+  g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model_sort), NULL);
+  g_return_val_if_fail (child_path != NULL, NULL);
 
-  return retval;
+  return gtk_tree_model_sort_convert_path_real (tree_model_sort, child_path, TRUE);
 }
 
 static void
@@ -397,7 +372,13 @@ gtk_tree_model_sort_changed (GtkTreeModel *s_model,
       s_path = gtk_tree_model_get_path (s_model, s_iter);
     }
 
-  path = gtk_tree_model_sort_convert_path (tree_model_sort, s_path);
+  path = gtk_tree_model_sort_convert_path_real (tree_model_sort, s_path, FALSE);
+  if (path == NULL)
+    {
+      if (free_s_path)
+       gtk_tree_path_free (s_path);
+      return;
+    }
   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
   gtk_signal_emit_by_name (GTK_OBJECT (data), "changed", path, &iter);
 
@@ -406,7 +387,8 @@ gtk_tree_model_sort_changed (GtkTreeModel *s_model,
     gtk_tree_path_free (s_path);
 }
 
-static void
+/* FALSE if the value was inserted, TRUE otherwise */
+static gboolean
 gtk_tree_model_sort_insert_value (GtkTreeModelSort *sort,
                                  GtkTreePath      *s_path,
                                  GtkTreeIter      *s_iter)
@@ -417,7 +399,7 @@ gtk_tree_model_sort_insert_value (GtkTreeModelSort *sort,
   SortElt elt;
   SortElt *tmp_elt;
   gint offset;
-  gint high, low, middle, j;
+  gint middle, j;
   GValueCompareFunc func;
   GValue s_value = {0, };
   GValue tmp_value = {0, };
@@ -428,21 +410,28 @@ gtk_tree_model_sort_insert_value (GtkTreeModelSort *sort,
   elt.ref = 0;
   elt.children = NULL;
   elt.offset = offset;
+
   tmp_path = gtk_tree_path_copy (s_path);
+
   if (gtk_tree_path_up (tmp_path))
     {
       GtkTreePath *parent_path;
 
-      parent_path = gtk_tree_model_sort_convert_path (sort, tmp_path);
+      parent_path = gtk_tree_model_sort_convert_path_real (sort, tmp_path, FALSE);
+      if (parent_path == NULL)
+       {
+         gtk_tree_path_free (tmp_path);
+         return FALSE;
+       }
       gtk_tree_model_get_iter (GTK_TREE_MODEL (sort), &iter, parent_path);
       elt.parent = ((SortElt *) iter.tree_node);
       array = ((SortElt *) iter.tree_node)->children;
+      gtk_tree_path_free (parent_path);
       if (array == NULL)
        {
-         ((SortElt *) iter.tree_node)->children = g_array_sized_new (FALSE, FALSE, sizeof (SortElt), 1);
-         array = ((SortElt *) iter.tree_node)->children;
+         gtk_tree_path_free (tmp_path);
+         return FALSE;
        }
-      gtk_tree_path_free (parent_path);
     }
   else
     {
@@ -453,25 +442,9 @@ gtk_tree_model_sort_insert_value (GtkTreeModelSort *sort,
     }
   gtk_tree_path_free (tmp_path);
 
-  if (sort->func)
-    func = sort->func;
-  else
-    {
-      switch (gtk_tree_model_get_column_type (sort->child_model, sort->sort_col))
-       {
-       case G_TYPE_STRING:
-         func = &g_value_string_compare_func;
-         break;
-       case G_TYPE_INT:
-         func = &g_value_int_compare_func;
-         break;
-       default:
-         g_warning ("No comparison function for row %d (Type %s)\n",
-                    sort->sort_col,
-                    g_type_name (gtk_tree_model_get_column_type (sort->child_model, sort->sort_col)));
-         return;
-       }
-    }
+  func = (GValueCompareFunc) gtk_tree_model_sort_get_func (sort);
+
+  g_return_val_if_fail (func != NULL, FALSE);
 
   gtk_tree_model_get_value (sort->child_model, s_iter, sort->sort_col, &s_value);
 
@@ -535,6 +508,8 @@ gtk_tree_model_sort_insert_value (GtkTreeModelSort *sort,
              j != middle)
            tmp_elt->offset ++;
        }
+
+  return TRUE;
 }
 
 static void
@@ -566,12 +541,13 @@ gtk_tree_model_sort_inserted (GtkTreeModel *s_model,
       else
        real_s_iter = (* s_iter);
 
-      gtk_tree_model_sort_insert_value (tree_model_sort, s_path, &real_s_iter);
+      if (!gtk_tree_model_sort_insert_value (tree_model_sort, s_path, &real_s_iter))
+       return;
     }
 
-  path = gtk_tree_model_sort_convert_path (tree_model_sort, s_path);
-
-  g_return_if_fail (path != NULL);
+  path = gtk_tree_model_sort_convert_path_real (tree_model_sort, s_path, FALSE);
+  if (path == NULL)
+    return;
 
   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
   gtk_signal_emit_by_name (GTK_OBJECT (data), "inserted", path, &iter);
@@ -603,7 +579,9 @@ gtk_tree_model_sort_child_toggled (GtkTreeModel *s_model,
       free_s_path = TRUE;
     }
 
-  path = gtk_tree_model_sort_convert_path (tree_model_sort, s_path);
+  path = gtk_tree_model_sort_convert_path_real (tree_model_sort, s_path, FALSE);
+  if (path == NULL)
+    return;
   gtk_tree_model_get_iter (GTK_TREE_MODEL (data), &iter, path);
   gtk_signal_emit_by_name (GTK_OBJECT (data),
                           "child_toggled",
@@ -805,6 +783,7 @@ gtk_tree_model_sort_iter_children (GtkTreeModel *tree_model,
 
   g_return_val_if_fail (GTK_IS_TREE_MODEL_SORT (tree_model), FALSE);
   g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->child_model != NULL, FALSE);
+
   if (parent)
     g_return_val_if_fail (GTK_TREE_MODEL_SORT (tree_model)->stamp == parent->stamp, FALSE);
 
@@ -936,6 +915,81 @@ gtk_tree_model_sort_unref_iter (GtkTreeModel *tree_model,
 }
 
 /* Internal functions */
+static GtkTreePath *
+gtk_tree_model_sort_convert_path_real (GtkTreeModelSort *tree_model_sort,
+                                      GtkTreePath      *child_path,
+                                      gboolean          build_children)
+{
+  GtkTreePath *retval;
+  GArray *array;
+  gint *indices;
+  gint i = 0;
+
+  if (tree_model_sort->root == NULL)
+    {
+      if (build_children)
+       gtk_tree_model_sort_build_level (tree_model_sort, NULL);
+      else
+       return FALSE;
+    }
+
+  retval = gtk_tree_path_new ();
+  array = (GArray *) tree_model_sort->root;
+  indices = gtk_tree_path_get_indices (child_path);
+
+  do
+    {
+      SortElt *elt;
+      gboolean found = FALSE;
+      gint j;
+
+      if ((array->len < indices[i]) || (array == NULL))
+       {
+         gtk_tree_path_free (retval);
+         return NULL;
+       }
+
+      elt = (SortElt *) array->data;
+      for (j = 0; j < array->len; j++, elt++)
+       {
+         if (elt->offset == indices[i])
+           {
+             found = TRUE;
+             break;
+           }
+       }
+      if (! found)
+       {
+         gtk_tree_path_free (retval);
+         return NULL;
+       }
+
+      gtk_tree_path_prepend_index (retval, j);
+
+      i++;
+
+      if (i == gtk_tree_path_get_depth (child_path))
+       break;
+
+      if (elt->children == NULL)
+       {
+         if (build_children)
+           {
+             gtk_tree_path_prepend_index (retval, j);
+             gtk_tree_model_sort_build_level (tree_model_sort, elt);
+           }
+         else
+           {
+             gtk_tree_path_free (retval);
+             return NULL;
+           }
+       }
+    }
+  while (TRUE);
+
+  return retval;
+}
+  
 static void
 gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
                                 SortElt          *place)
@@ -945,6 +999,7 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
   GtkTreeIter *parent_iter = NULL;
   GtkTreeIter iter;
   SortElt elt;
+  SortData sort_data;
 
   if (place)
     parent_iter = & (place->iter);
@@ -979,6 +1034,11 @@ gtk_tree_model_sort_build_level (GtkTreeModelSort *tree_model_sort,
     }
   while (gtk_tree_model_iter_next (tree_model_sort->child_model, &iter));
 
+  sort_data.func = (GValueCompareFunc) gtk_tree_model_sort_get_func (tree_model_sort);
+  sort_data.model = tree_model_sort->child_model;
+  sort_data.sort_col = tree_model_sort->sort_col;
+
+  g_array_sort_with_data (children, gtk_tree_model_sort_func, &sort_data);
 }
 
 static void
@@ -1001,7 +1061,58 @@ gtk_tree_model_sort_free_level (GArray *array)
   g_array_free (array, TRUE);
 }
 
-gint
+static GFunc
+gtk_tree_model_sort_get_func (GtkTreeModelSort *tree_model_sort)
+{
+  GValueCompareFunc func;
+  if (tree_model_sort->func)
+    func = tree_model_sort->func;
+  else
+    {
+      switch (gtk_tree_model_get_column_type (tree_model_sort->child_model,
+                                             tree_model_sort->sort_col))
+       {
+       case G_TYPE_STRING:
+         func = &g_value_string_compare_func;
+         break;
+       case G_TYPE_INT:
+         func = &g_value_int_compare_func;
+         break;
+       default:
+         g_warning ("No comparison function for row %d (Type %s)\n",
+                    tree_model_sort->sort_col,
+                    g_type_name (gtk_tree_model_get_column_type (tree_model_sort->child_model,
+                                                                 tree_model_sort->sort_col)));
+         return NULL;
+       }
+
+    }
+  return (GFunc) func;
+}
+
+static gint
+gtk_tree_model_sort_func  (gconstpointer a,
+                          gconstpointer b,
+                          gpointer      user_data)
+{
+  GValue value_a;
+  GValue value_b;
+  SortData *sort_data = user_data;
+  gint retval;
+
+  gtk_tree_model_get_value (sort_data->model, (GtkTreeIter *) a, sort_data->sort_col, &value_a);
+  gtk_tree_model_get_value (sort_data->model, (GtkTreeIter *) b, sort_data->sort_col, &value_b);
+
+  retval = (sort_data->func) (&value_a, &value_b);
+
+  g_value_unset (&value_a);
+  g_value_unset (&value_b);
+
+  return retval;
+}
+  
+
+static gint
 g_value_string_compare_func (const GValue *a,
                             const GValue *b)
 {
@@ -1016,7 +1127,7 @@ g_value_string_compare_func (const GValue *a,
   return strcmp (a_str, b_str);
 }
 
-gint
+static gint
 g_value_int_compare_func (const GValue *a,
                          const GValue *b)
 {
index b3469f508f90e46398b5ee602bb87d3dd130e97c..2aa1c3484d63f240d66e48363a17f50511981a7b 100644 (file)
@@ -117,20 +117,26 @@ iter_insert_after (GtkWidget *button, GtkTreeView *tree_view)
                                       NULL,
                                       &selected))
     {
-      gtk_tree_store_insert_after (model,
-                                  &iter,
-                                  NULL,
-                                  &selected);
+      if (GTK_IS_TREE_STORE (model))
+       {
+         gtk_tree_store_insert_after (model,
+                                      &iter,
+                                      NULL,
+                                      &selected);
+         node_set (&iter);
+       }
     }
   else
     {
-      gtk_tree_store_insert_after (model,
-                                  &iter,
-                                  NULL,
-                                  &selected);
+      if (GTK_IS_TREE_STORE (model))
+       {
+         gtk_tree_store_insert_after (model,
+                                      &iter,
+                                      NULL,
+                                      &selected);
+         node_set (&iter);
+       }
     }
-
-  node_set (&iter);
 }
 
 static void
@@ -219,7 +225,7 @@ make_window (gboolean use_sort)
       GtkTreeModel *sort_model;
 
       sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (base_model),
-                                                      NULL, 0);
+                                                      NULL, 1);
       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (sort_model));
     }
   else
@@ -300,6 +306,9 @@ make_window (gboolean use_sort)
       iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
       iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
       iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
+      iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
+      iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
+      iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
     }
   /* Show it all */
   gtk_widget_show_all (window);
index b3469f508f90e46398b5ee602bb87d3dd130e97c..2aa1c3484d63f240d66e48363a17f50511981a7b 100644 (file)
@@ -117,20 +117,26 @@ iter_insert_after (GtkWidget *button, GtkTreeView *tree_view)
                                       NULL,
                                       &selected))
     {
-      gtk_tree_store_insert_after (model,
-                                  &iter,
-                                  NULL,
-                                  &selected);
+      if (GTK_IS_TREE_STORE (model))
+       {
+         gtk_tree_store_insert_after (model,
+                                      &iter,
+                                      NULL,
+                                      &selected);
+         node_set (&iter);
+       }
     }
   else
     {
-      gtk_tree_store_insert_after (model,
-                                  &iter,
-                                  NULL,
-                                  &selected);
+      if (GTK_IS_TREE_STORE (model))
+       {
+         gtk_tree_store_insert_after (model,
+                                      &iter,
+                                      NULL,
+                                      &selected);
+         node_set (&iter);
+       }
     }
-
-  node_set (&iter);
 }
 
 static void
@@ -219,7 +225,7 @@ make_window (gboolean use_sort)
       GtkTreeModel *sort_model;
 
       sort_model = gtk_tree_model_sort_new_with_model (GTK_TREE_MODEL (base_model),
-                                                      NULL, 0);
+                                                      NULL, 1);
       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (sort_model));
     }
   else
@@ -300,6 +306,9 @@ make_window (gboolean use_sort)
       iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
       iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
       iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
+      iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
+      iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
+      iter_prepend (NULL, GTK_TREE_VIEW (tree_view));
     }
   /* Show it all */
   gtk_widget_show_all (window);